package main

import (
	"fmt"
	"math/rand"
	"time"
)

// START0 OMIT
type Message struct {
	str  string
	wait chan bool // HL
}

// STOP0 OMIT

func main() {
	c := fanIn(ennuyeux("Joe"), ennuyeux("Ann")) // HL
	// START1 OMIT
	for i := 0; i < 5; i++ {
		msg1 := <-c
		fmt.Println(msg1.str)
		msg2 := <-c
		fmt.Println(msg2.str)
		msg1.wait <- true
		msg2.wait <- true
	}
	// STOP1 OMIT
	fmt.Println("Vous êtes tous les deux ennuyeuxs, je m'en vais!")
}

func ennuyeux(msg string) <-chan Message { // Retourne un channel en lecture seule. // HL
	c := make(chan Message)
	// START2 OMIT
	waitForIt := make(chan bool) // Partagé par tous les messages.
	// STOP2 OMIT
	go func() { // On lance la nouvelle goroutine depuis la fonction. // HL
		for i := 0; ; i++ {
			// START3 OMIT
			c <- Message{fmt.Sprintf("%s: %d", msg, i), waitForIt}
			time.Sleep(time.Duration(rand.Intn(2e3)) * time.Millisecond)
			<-waitForIt
			// STOP3 OMIT
		}
	}()
	return c // Retourne le channel à celui qui a appellé la fonction. // HL
}

// START3 OMIT
func fanIn(inputs ...<-chan Message) <-chan Message { // HL
	c := make(chan Message)
	for i := range inputs {
		input := inputs[i] // Nouvelle instance de 'input' pour chaque loop.
		go func() {
			for {
				c <- <-input
			}
		}()
	}
	return c
}

// STOP3 OMIT
